package com.project.api.sale.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpSession;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;

@RestController
public class WeChatController {

    private Logger logger = LoggerFactory.getLogger(getClass());
    @Autowired
    private  WechatContants wechatContants;

    // URL:   http://www.xxxx.com/tokencheck/
    // Token: 此处TOKEN即为微信接口配置信息的Token

    private String TOKEN = "wensdi";

    /**
     * 验证微信后台配置的服务器地址有效性
     *
     * 接收并校验四个请求参数
     *
     * @param signature 微信加密签名
     * @param timestamp 时间戳
     * @param nonce     随机数
     * @param echostr   随机字符串
     * @return echostr
     */
    @RequestMapping(value = "/tokencheck", method = RequestMethod.GET)
    public String checkName(@RequestParam(name = "signature") String signature,
                            @RequestParam(name = "timestamp") String timestamp,
                            @RequestParam(name = "nonce") String nonce,
                            @RequestParam(name = "echostr") String echostr) {

        logger.info("微信-开始校验签名");
        logger.info("收到来自微信的 echostr 字符串:{}", echostr);

//        加密/校验流程如下:
//        1. 将token、timestamp、nonce三个参数进行字典序排序
//        2. 将三个参数字符串拼接成一个字符串进行sha1加密
//        3. 开发者获得加密后的字符串可与signature对比，标识该请求来源于微信

        // 1.排序
        String sortString = sort(TOKEN, timestamp, nonce);
        // 2.sha1加密
        String myString = sha1(sortString);
        // 3.字符串校验
        if (myString != null && myString != "" && myString.equals(signature)) {
            logger.info("微信-签名校验通过");
            //如果检验成功原样返回echostr，微信服务器接收到此输出，才会确认检验完成。
            logger.info("回复给微信的 echostr 字符串:{}", echostr);
            return echostr;
        } else {
            logger.error("微信-签名校验失败");
            return "";
        }
    }

    @RequestMapping(value = "/tokencheck", method = RequestMethod.POST)
    public void messageHandler(){

    }

    /**
     * 排序方法
     * @param token     Token
     * @param timestamp 时间戳
     * @param nonce     随机数
     * @return
     */
    public String sort(String token, String timestamp, String nonce) {
        String[] strArray = {token, timestamp, nonce};
        Arrays.sort(strArray);
        StringBuilder sb = new StringBuilder();
        for (String str : strArray) {
            sb.append(str);
        }

        return sb.toString();
    }

    /**
     * 将字符串进行sha1加密
     *
     * @param str 需要加密的字符串
     * @return    加密后的内容
     */
    public String sha1(String str) {
        try {
            MessageDigest digest = MessageDigest.getInstance("SHA-1");
            digest.update(str.getBytes());
            byte messageDigest[] = digest.digest();
            // 创建 16进制字符串
            StringBuffer hexString = new StringBuffer();
            // 字节数组转换为 十六进制 数
            for (int i = 0; i < messageDigest.length; i++) {
                String shaHex = Integer.toHexString(messageDigest[i] & 0xFF);
                if (shaHex.length() < 2) {
                    hexString.append(0);
                }
                hexString.append(shaHex);
            }
            return hexString.toString();

        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return "";
    }

    /**
     * 功能描述：配置网页授权域名验证
     * @return
     */
    @RequestMapping("/MP_verify_6ZOnQ2PaNeAweKfu.txt")
    public String verifyCheck(){
        return "6ZOnQ2PaNeAweKfu";

    }

    @RequestMapping("/mallIndex")
    public ModelAndView skipIndex(@RequestParam(name = "code") String code, HttpSession httpSession){
        System.out.println("code是：" + code);
        WebAccessToken webAccessToken = new WebAccessToken();
        String  tokenUrl = WechatApiUrlConstants.ACCESS_WEBTOKEN_URL.replace("APPID",wechatContants.getAppid()).replace("SECRET",wechatContants.getSecret()).replace("CODE", code);
        String result = HttpsUtil.httpsRequestToString(tokenUrl, "GET", null);
        JSONObject jsonObject = JSON.parseObject(result);

        if (jsonObject.containsKey("errcode")){
            //如果接收到的结果中有错误代码信息则本次获取信息错误
            System.out.println("网页授权码access_token获取错误，错误信息为：" + jsonObject.getString("errmsg"));
        }else {
            System.out.println("网页授权码access_token获取成功，获取到的access_token为：" + jsonObject.getString("access_token"));

            webAccessToken.setAccess_token(jsonObject.getString("access_token"));
            webAccessToken.setExpires_in(jsonObject.getInteger("expires_in"));
            webAccessToken.setRefresh_token(jsonObject.getString("refresh_token"));
            webAccessToken.setOpenid(jsonObject.getString("openid"));
            webAccessToken.setScope(jsonObject.getString("scope"));
        }

        System.out.println("获取到的access_token为：" + jsonObject);

        httpSession.setAttribute("openid",webAccessToken.getOpenid());
        httpSession.setAttribute("access_token", webAccessToken.getAccess_token());

        ModelAndView mv = new ModelAndView("redirect:/index.html");

        return mv;
    }

    /**
     * 定时从微信服务器上面获取token值
     */
    //@Scheduled(fixedRate=20000) ////测试每20秒执行一次
//    @Scheduled(cron="0/5 * *  * * ? ")   //测试每5秒执行一次
//    @Scheduled(initialDelay = 1000, fixedDelay = 7000*1000)   //每7000秒执行一次
    //@Scheduled(cron = "0 0 */2 * * ?")  //俩小时执行一次
    public void getAccessToken() {
        logger.info("into  getAccessToken");
        RestTemplate restTemplate =new RestTemplate();
        String  tokenUrl=WechatApiUrlConstants.ACCESS_TOKEN_URL.replace("APPID",wechatContants.getAppid()).replace("APPSECRET",wechatContants.getSecret());
        AccessTokenUtil.accessToken=restTemplate.getForObject(tokenUrl,AccessToken.class);
        logger.info("access_token:"+AccessTokenUtil.accessToken.getAccess_token());
        logger.info("expires_in:"+AccessTokenUtil.accessToken.getExpires_in());
    }


}